// Copyright 2011-2012, Vanya Davidenko.
// Используемая кодировка: UTF-8.

#ifndef LIBV_ACFILE_H_
#define LIBV_ACFILE_H_

#if defined(_WIN32) || defined(__CYGWIN__)
# include <libv/windows_lean.h>
typedef OVERLAPPED RequestHandle;

#elif defined(__linux__)
# include <aio.h>
typedef aiocb RequestHandle;

#else
# error "This header should be used in Windows or Linux 2.6+."
#endif

#include <string>
#include <libv/stdint.h>
#include <libv/file/afile.h>
#include <libv/file/basic_request_handle.h>



namespace libv
{

class ACFile : public AFile
{
  public:
    typedef AFile::OpenType OpenType;
    typedef AFile::LockType LockType;
    typedef AFile::PreallocType PreallocType;
    typedef AFile::Prealloc Prealloc;


    class RequestCompletionHandle : public BasicRequestHandle
    {
      friend class ACFile;
      public:
        inline RequestCompletionHandle();

        inline RequestCompletionHandle(FileHandle file_handle,
                                       const RequestHandle& request_handle,
                                       const uint32_t& num_bytes_to_transfer,
                                       enum Operation operation);

        inline RequestCompletionHandle(const RequestCompletionHandle& rhv);

        inline ~RequestCompletionHandle();

        inline RequestCompletionHandle& operator=(
            const RequestCompletionHandle& rhv);

        inline Status Status() const;

        // После возврата true необходимо проверить статус.
        inline bool WaitUntilFinished() const;

        inline void Clear();


      private:
        inline void Destruct();

        inline FileSlice RequestHandle2FileSilce(
            const RequestHandle& request_handle,
            const uint32_t num_bytes_to_transfer) const;

        inline enum Status StatusImpl() const;
        inline bool WaitUntilFinishedImpl() const;
        inline void DestructImpl();


        RequestHandle* request_handle_;
        int* ref_count_;
    };



    inline bool Open(const ::std::string& file_path,
                     const int open_type,
                     const bool enable_read_ahead_caching = true) const;


    inline bool Open(const ::std::string& file_path,
                     const int open_type,
                     const bool enable_read_ahead_caching = true);


    inline bool Write(const fpos64& offset,
                      const void* data,
                      const uint32_t data_size,
                      RequestCompletionHandle* completion_handle);


    inline bool Read(const fpos64& offset,
                     volatile void* buffer,
                     const uint32_t buffer_size,
                     RequestCompletionHandle* completion_handle) const;

  private:
    inline bool OpenImpl(const ::std::string& file_path,
                         const int open_type,
                         const bool enable_read_ahead_caching,
                         const bool read_only) const;


    inline bool WriteImpl(const fpos64& offset,
                          const void* data,
                          const uint32_t data_size,
                          RequestCompletionHandle* completion_handle);


    inline bool ReadImpl(const fpos64& offset,
                         volatile void* buffer,
                         const uint32_t buffer_size,
                         RequestCompletionHandle* completion_handle) const;

#ifdef _WIN32
    inline bool InitOverlapped(const fpos64 offset,
                               OVERLAPPED* overlapped) const;
#endif
};

}  // libv



#include <libv/file/request_completion_handle.hpp>
#include <libv/file/acfile.hpp>
#if defined(_WIN32)
# include <libv/file/windows/request_completion_handle_impl.hpp>
# include <libv/file/windows/acfile_impl.hpp>
#elif defined(__linux__)
# include <libv/file/linux/request_completion_handle_impl.hpp>
# include <libv/file/linux/acfile_impl.hpp>
#else
# error "This header should be used in Windows or Linux 2.6+."
#endif

#endif  // LIBV_ACFILE_H_
